import redis
from config import PROXIES_REDIS
import asyncio
import time
import random

POOL = redis.ConnectionPool(host=PROXIES_REDIS['HOST'], port=PROXIES_REDIS[
                            'PORT'], db=PROXIES_REDIS['DB'])
REDIS = redis.StrictRedis(connection_pool=POOL)

_global_proxy_list = []


class Singleton(type):
    def __init__(self, *args, **kwargs):
        self.__instance = None
        super().__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super().__call__(*args, **kwargs)
            return self.__instance
        else:
            return self.__instance


class PROXY(metaclass=Singleton):

    def __init__(self, async_flag=False):
        self.reflash_pool()

    def _get_all_proxy(self):
        def fr(bit):
            return bit.decode('utf8')
        while True:
            count = REDIS.zcount(PROXIES_REDIS['DOCUMENT_NAME'], 0, 20)
            if count == 0:
                print('wait 60s no proxy')
                if async_flag:
                    self.async_sleep(60)
                else:
                    time.sleep(60)
                continue
            ret = REDIS.zrange(PROXIES_REDIS['DOCUMENT_NAME'], 0, count)
            if not ret:
                continue
            return list(map(fr, ret))

    def get_random_proxy(self):
        while 1:
            if len(self.proxy_pool) < 2:
                self.reflash_pool()
                time.sleep(60)
            my_id = random.randint(0, len(self.proxy_pool) - 1)
            proxy = self.proxy_pool[my_id]
            if proxy:
                return proxy

    def remove_proxy(self, host_proxy):
        index = self.proxy_pool.index(host_proxy)
        del self.proxy_pool[index]
        return True

    def reflash_pool(self):
        global _global_proxy_list
        if _global_proxy_list:
            self.proxy_pool = _global_proxy_list
        else:
            self.proxy_pool = self._get_all_proxy()
            _global_proxy_list = self.proxy_pool

    async def async_sleep(self, times):
        await asyncio.sleep(times)
